package com.example.cm_base

import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.fragment.app.Fragment
import androidx.lifecycle.ViewModel
import androidx.lifecycle.ViewModelProvider
import androidx.viewbinding.ViewBinding
import java.lang.reflect.ParameterizedType

/**
 * 具有ViewModel和ViewBinding支持的基础Fragment
 * 通过反射自动创建对应的ViewModel和ViewBinding实例
 *
 * 使用方法：
 * 1. 继承此BaseFragment
 * 2. 指定泛型参数VB (ViewBinding) 和 VM (ViewModel)
 * 3. 重写onFragmentCreated方法处理视图逻辑
 */
abstract class BaseFragment<VB : ViewBinding, VM : ViewModel, SVM : ViewModel> : Fragment() {

    private var _binding: VB? = null

    // ViewBinding属性，在onCreateView到onDestroyView期间有效
    protected val binding: VB
        get() = _binding ?: throw IllegalStateException("在Fragment视图生命周期外访问binding")

    // ViewModel实例
    protected lateinit var viewModel: VM
        private set

    // ViewModel实例
    protected lateinit var shareViewModel: SVM
        private set

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)

        viewModel = initViewModel()
        if (sharedViewModel()) {
            shareViewModel = initShareViewModel()
        }
    }

    override fun onCreateView(
        inflater: LayoutInflater,
        container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View? {
        _binding = initViewBinding(inflater, container)
        return binding.root
    }

    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)

        initObservers()
        onFragmentCreated(view, savedInstanceState)
    }

    override fun onDestroyView() {
        super.onDestroyView()
        _binding = null
    }

    /**
     * 使用反射创建ViewBinding实例
     */
    @Suppress("UNCHECKED_CAST")
    private fun initViewBinding(inflater: LayoutInflater, container: ViewGroup?): VB {
        try {
            val type = (javaClass.genericSuperclass as ParameterizedType)
                .actualTypeArguments[0] as Class<VB>
            val inflateMethod = type.getDeclaredMethod(
                "inflate",
                LayoutInflater::class.java,
                ViewGroup::class.java,
                Boolean::class.java
            )
            return inflateMethod.invoke(null, inflater, container, false) as VB
        } catch (e: Exception) {
            when (e) {
                is ClassCastException -> throw RuntimeException(
                    "ViewBinding泛型类型错误，请检查是否正确指定了ViewBinding类型", e
                )
                is IndexOutOfBoundsException -> throw RuntimeException(
                    "未指定ViewBinding泛型参数", e
                )
                is NoSuchMethodException -> throw RuntimeException(
                    "ViewBinding类缺少inflate方法，请检查是否是正确的ViewBinding类", e
                )
                is IllegalAccessException, is java.lang.reflect.InvocationTargetException -> throw RuntimeException(
                    "ViewBinding inflate方法调用失败：${e.message}", e
                )
                else -> throw RuntimeException(
                    "ViewBinding初始化失败: ${e.message}", e
                )
            }
        }
    }

    @Suppress("UNCHECKED_CAST")
    private fun initViewModel(): VM {
        try {
            val type = (javaClass.genericSuperclass as ParameterizedType)
                .actualTypeArguments[1] as Class<VM>
            return ViewModelProvider(this)[type]
        } catch (e: Exception) {
            when (e) {
                is ClassCastException -> throw RuntimeException(
                    "ViewModel泛型类型错误，请检查是否正确指定了ViewModel类型", e
                )
                is IndexOutOfBoundsException -> throw RuntimeException(
                    "未指定ViewModel泛型参数", e
                )
                is IllegalArgumentException -> throw RuntimeException(
                    "ViewModel构造失败，请确保ViewModel有无参构造函数或使用带参数的ViewModelProvider.Factory", e
                )
                is RuntimeException -> {
                    if (e.message?.contains("Cannot create an instance of") == true) {
                        throw RuntimeException(
                            "ViewModel实例化失败，请确保ViewModel类不是抽象类且有正确的构造函数", e
                        )
                    } else {
                        throw e
                    }
                }
                else -> throw RuntimeException(
                    "ViewModel初始化失败: ${e.message}", e
                )
            }
        }
    }

    private fun initShareViewModel(): SVM {
        try {
            val type = (javaClass.genericSuperclass as ParameterizedType)
                .actualTypeArguments[2] as Class<SVM>
            return ViewModelProvider(requireActivity())[type]
        } catch (e: Exception) {
            when (e) {
                is ClassCastException -> throw RuntimeException("共享ViewModel类型转换失败", e)
                is IndexOutOfBoundsException -> throw RuntimeException("未指定共享ViewModel类型", e)
                else -> throw RuntimeException("共享ViewModel初始化失败: ${e.message}", e)
            }
        }
    }

    protected open fun sharedViewModel(): Boolean = false


    /**
     * 子类可以重写此方法来设置数据观察者
     */
    protected open fun initObservers() {
    }

    /**
     * 子类必须实现此方法进行Fragment视图创建后的初始化
     */
    protected abstract fun onFragmentCreated(view: View, savedInstanceState: Bundle?)


} 